import cornerstoneDICOMImageLoader from "@cornerstonejs/dicom-image-loader";

import {
	trimLeft,
	desensitizeSubstring,
	readTagAsString,
	decodeChinese,
	formartDcmDate,
	formartDcmTime,
	getNSpace
} from "@/utils";

import {
	RenderingEngine,
	getRenderingEngine,
	Enums,
	metaData,
	imageLoader
} from "@cornerstonejs/core";

import { renderingEngineId2d } from "../cornerstone3D";
import { DcmTagsDesc } from "./DcmTagsDesc";

const { ViewportType } = Enums;

export default class DCMImage {
	constructor(args) {
		this.series = null; // 所属序列
		this.parsed = false; // 是否已解析
		this.imageId = "";
		this.studyInsUid = "";
		this.seriesInsUid = "";
		this.sopInsUid = "";
		this.instanceNumber = 1;
		this.mime = "dcm";
		this.pdfUrl = null;
		this.width = 0;
		this.height = 0;
		this.defWW = 400;
		this.defWL = 40;
		this.thickness = 0;
		this.ps_col = null;
		this.ps_row = null;
		this.io_r_x = 1;
		this.io_r_y = 0;
		this.io_r_z = 0;
		this.io_c_x = 0;
		this.io_c_y = 1;
		this.io_c_z = 0;
		this.ip_x = 0;
		this.ip_y = 0;
		this.ip_z = 0;
		this.numberOfFrames = 1;
		this.frameIds = [];

		// 2025.05.15 overlay
		this.overlay = {
			rows: 0,
			columns: 0,
			type: "",
			origin: [],
			bitsAllocated: 0,
			data: null
		};

		// 2024.09.27 qinwl 四角文字
		// 默认
		// 左上角
		this.PatientName = ""; // 姓名
		this.AgeAndSex = ""; // 年龄(或者生日)+性别
		this.RadiID = ""; // 影像号
		this.RegistryID = ""; // 登记号
		this.ImageComments = ""; // 图像说明
		this.MedicalID = ""; // 病历号
		this.EchoNumbers = ""; // 回波组号
		this.PatientID = ""; // 病人病号
		this.Laterality = ""; // 部位偏侧

		// 右上角
		this.Window = ""; // 窗宽窗位 动态变化
		// this.ImageNo = ""; // 图像序号
		this.SeriesNo = ""; // 序列号
		this.HR = ""; // 互认标识
		this.SeriesDateTime = ""; // 序列日期时间
		this.DFOV = ""; // 视场角
		this.StudyDateTime = ""; // 检查日期时间

		// 左下角
		this.HospitalName = ""; // 医院名称
		this.StudyDesc = ""; // 检查描述
		this.SeriesDesc = ""; // 序列描述
		this.ScanningSequence = ""; // 扫描序列
		this.PatientPosition = ""; // 患者位置
		this.DeviceName = ""; // 设备名称
		this.OperatorsName = ""; // 操作员姓名
		this.StudyDate = ""; // 检查日期
		this.AcquisitionDate = ""; // 采集日期
		this.AcquisitionTime = ""; // 采集时间
		this.ContentDate = ""; // 内容日期
		this.ContentTime = ""; // 内容时间
		this.Manufacturer = ""; // 制造商
		this.Position = ""; // 方位 0x200B, 0x1011

		// 右下角
		this.ThicknessLocation = ""; // 厚度位置
		this.Exposure = ""; // 曝光参数
		this.TrTe = ""; // 拍片参数
		this.ScaleRatio = ""; // 缩放比例   动态变化
		this.InversionTime = ""; // 倒转时间
		this.FlipAngle = ""; // 翻转角度
		this.AcquisitionDuration = ""; // 采集时长

		if (args) {
			// this.url = args.url;
			this.imageId = args.imageId;
		}
	}

	async parse() {
		// const image = await cornerstoneDICOMImageLoader.wadouri.loadImage(
		// 	this.imageId
		// ).promise;

		const image = await imageLoader.loadAndCacheImage(this.imageId);
		// console.log("parse, image: ", image);

		this.sopInsUid = image.data.string("x00080018"); // SOP Instance UID
		this.studyInsUid = image.data.string("x0020000d"); // Study Instance UID
		this.seriesInsUid = image.data.string("x0020000e"); // Series Instance UID
		this.instanceNumber = image.data.string("x00200013"); // Instance Number

		this.width = image.width;
		this.height = image.height;
		this.defWL = Math.round(image.windowCenter);
		this.defWW = Math.round(image.windowWidth);
		if (this.defWW <= 1) {
			this.defWW = 400;
			this.defWL = 40;
		}

		let val;
		let ps_img_col, ps_img_row;
		val = image.data.string("x00181164"); // Imager Pixel Spacing
		if (val) {
			ps_img_col = parseFloat(val.split("\\")[0]);
			ps_img_row = parseFloat(val.split("\\")[1]);
		}

		this.ps_col = image.columnPixelSpacing || ps_img_col;
		this.ps_row = image.rowPixelSpacing || ps_img_row;
		val = image.data.string("x00200037");
		if (val) {
			this.io_r_x = parseFloat(val.split("\\")[0]);
			this.io_r_y = parseFloat(val.split("\\")[1]);
			this.io_r_z = parseFloat(val.split("\\")[2]);
			this.io_c_x = parseFloat(val.split("\\")[3]);
			this.io_c_y = parseFloat(val.split("\\")[4]);
			this.io_c_z = parseFloat(val.split("\\")[5]);
		}

		// 多帧图
		this.numberOfFrames = image.data.intString("x00280008"); // Number of Frames
		if (this.numberOfFrames <= 0) this.numberOfFrames = 1;

		if (this.numberOfFrames > 1) {
			for (let i = 0; i < this.numberOfFrames; i++) {
				const frameId = this.imageId + "&frame=" + (i + 1);
				this.frameIds.push(frameId);
				await cornerstoneDICOMImageLoader.wadouri.loadImage(frameId).promise;
			}
		}

		val = image.data.string("x00200032");
		if (val) {
			this.ip_x = parseFloat(val.split("\\")[0]);
			this.ip_y = parseFloat(val.split("\\")[1]);
			this.ip_z = parseFloat(val.split("\\")[2]);
		}

		val = image.data.string("x00180050");
		if (val) this.thickness = parseFloat(val);

		// 2025.04.17 qinwl 四角文字
		this.readCornerText(image);

		// 如果是PDF文件，则获取PDF文件URL
		val = image.data.string("x00420012"); // mime type
		if (val === "application/pdf") {
			this.mime = val;
			const pdfTag = image.data.elements.x00420011;
			if (pdfTag) {
				const buffer = new Uint8Array(
					image.data.byteArray.buffer,
					pdfTag.dataOffset,
					pdfTag.length
				);
				this.pdfUrl = URL.createObjectURL(
					new Blob([buffer], {
						type: "application/pdf"
					})
				);
			}
		}

		// 2025.05.18 读取overlay数据
		// this.readOverlayData(image);

		this.parsed = true;
	}

	readCornerText(image) {
		const lang = "zh_CN";
		let charset = image.data.string("x00080005") || "ISO_IR 100";
		const isUtf8 = charset.indexOf("ISO_IR 192") != -1;
		const isCN = lang === "zh_CN";

		// debugger;
		// 左上角
		let val;
		let tag;
		// 姓名
		if (this.series && this.series.study && this.series.study.patientName) {
			val = this.series.study.patientName;
		} else {
			// val = src.data.string("x00100010");
			tag = image.data.elements["x00100010"]; // 姓名
			if (tag) {
				val = readTagAsString(image.data.byteArray, tag.dataOffset, tag.length);
			}
			if (val) {
				val = decodeChinese(val, isUtf8);
			}
		}
		if (config.desensitize) {
			val = desensitizeSubstring(val, 1, -1);
		}
		this.PatientName = val;
		val = image.data.string("x00101010"); // 年龄(或者生日)+性别
		if (!val || val.length <= 0) {
			val = image.data.string("x00100030");
			if (!val) val = "";
		} else {
			if (isCN) {
				val = val.replace(/Y|y/, "岁");
				val = val.replace(/M|m/, "月");
				val = val.replace(/D|d/, "天");
			}
		}
		let tmp = image.data.string("x00100040");
		if (!tmp || tmp.length <= 0) tmp = isCN ? "未知" : "UNKNOWN";
		if (isCN) {
			if (tmp === "M" || tmp === "m") tmp = "男";
			else if (tmp === "F" || tmp === "f") tmp = "女";
			else tmp = "未知";
		}
		val += " " + tmp;
		this.AgeAndSex = val.replace(/^0+/g, "");

		if (this.series && this.series.study && this.series.study.radiId) {
			this.RadiID = this.series.study.radiId; // 影像号
		} else {
			this.RadiID = image.data.string("x00080050"); // 影像号 x00080050 Accession Number
		}

		if (this.series && this.series.study && this.series.study.studyId) {
			this.RegistryID = this.series.study.studyId; // 登记号
		} else {
			this.RegistryID = image.data.string("x00200010"); // 登记号 x00200010 Study ID
		}

		val = image.data.string("x00204000"); // 图像说明
		if (val) {
			this.ImageComments = decodeChinese(val, isUtf8);
		}

		this.MedicalID = ""; // 病历号
		val = image.data.string("x00180086"); // 回波组号
		if (val) this.EchoNumbers = val;
		this.PatientID = image.data.string("x00100020"); // 病人病号
		val = image.data.string("x0180015"); // 部位偏侧
		if (val) this.Laterality = val;
		val = image.data.string("x00200060");
		if (val) {
			if (this.Laterality !== "") this.Laterality += "/";
			this.Laterality += val;
		}

		val = image.data.string("x00200011"); // 序列号
		if (val) this.SeriesNo = "Se:" + val;
		this.HR = config.customhr || ""; // 互认标识

		// 序列日期时间
		val = "";
		if (this.series && this.series.seriesDate) val = this.series.seriesDate;
		else val = image.data.string("x00080021"); // 序列日期
		if (val) {
			this.SeriesDateTime = formartDcmDate(val);
		}
		val = "";
		if (this.series && this.series.seriesTime) val = this.series.seriesTime;
		else val = image.data.string("x00080031"); // 序列时间
		if (val) {
			this.SeriesDateTime += " " + formartDcmTime(val);
		}

		let dFov = image.width * image.columnPixelSpacing; // 视场角
		dFov = dFov.toFixed(2);
		this.DFOV = "DFOV:" + dFov + "mm";

		if (this.series && this.series.study && this.series.study.studyDate)
			this.StudyDateTime = this.series.study.studyDate; // 检查日期时间
		else {
			val = "";
			val = image.data.string("x00080020"); // 检查日期
			if (val) {
				this.StudyDateTime = formartDcmDate(val);
			}
			val = "";
			val = image.data.string("x00080030"); // 检查时间
			if (val) {
				this.StudyDateTime += " " + formartDcmTime(val);
			}
		}

		val = "";
		tag = image.data.elements["x00080080"]; // 医院名称
		if (tag) {
			val = readTagAsString(image.data.byteArray, tag.dataOffset, tag.length);
		}

		if (val) {
			val = decodeChinese(val, isUtf8);

			if (config.desensitize) {
				val = desensitizeSubstring(val, 3, val.length - 2);
			}
			this.HospitalName = val;
		}

		val = "";
		tag = image.data.elements["x00081030"]; // 检查描述
		if (tag) {
			val = readTagAsString(image.data.byteArray, tag.dataOffset, tag.length);
		}

		if (val) {
			this.StudyDesc = decodeChinese(val, isUtf8);
			this.StudyDesc = trimLeft(this.StudyDesc);
		}

		val = "";
		tag = image.data.elements["x0008103e"]; // 序列描述
		if (tag) {
			val = readTagAsString(image.data.byteArray, tag.dataOffset, tag.length);
		}

		if (val) {
			this.SeriesDesc = decodeChinese(val, isUtf8);
			this.SeriesDesc = trimLeft(this.SeriesDesc);
		}

		val = image.data.string("x00180020"); // 序列类型
		if (val) this.ScanningSequence = val;
		val = image.data.string("x00185100"); // 患者位置
		if (val) this.PatientPosition = val;
		if (this.series && this.series.study && this.series.study.modality)
			this.DeviceName = this.series.study.modality; // 设备名称
		else this.DeviceName = image.data.string("x00080060"); // 设备名称 x00080060 Device Name

		val = image.data.string("x00081070"); // 操作员姓名
		if (val) this.OperatorsName = val;

		if (this.series && this.series.study && this.series.study.studyDate) {
			this.StudyDate = this.series.study.studyDate; // 检查日期
		} else {
			val = image.data.string("x00080020"); // 检查日期 x00080020 Study Date
			this.StudyDate = formartDcmDate(val);
		}

		val = image.data.string("x00080022"); // 接收日期
		if (val) {
			this.AcquisitionDate = formartDcmDate(val);
		}
		val = image.data.string("x00080032"); // TA
		if (val) {
			this.AcquisitionTime = formartDcmTime(val);
		}

		val = image.data.string("x00080023"); // 内容日期
		if (val) {
			this.ContentDate = formartDcmDate(val);
		}
		val = image.data.string("x00080033"); // 内容时间
		if (val) {
			this.ContentTime = formartDcmTime(val);
		}

		val = "";
		tag = image.data.elements["x00080070"]; // 检查描述
		if (tag) {
			val = readTagAsString(image.data.byteArray, tag.dataOffset, tag.length);
		}

		if (val) {
			this.Manufacturer = decodeChinese(val, isUtf8);
		}

		val = image.data.string("x200B1011"); // 方位 0x200B, 0x1011
		if (val) this.Position = val;

		val = image.data.string("x00180050"); // 厚度位置
		if (val) {
			val = "T:" + parseFloat(val).toFixed(1);
		}
		tmp = image.data.string("x00200032", 2);
		if (tmp) {
			val += " L:" + parseFloat(tmp).toFixed(1);
		}
		this.ThicknessLocation = val;

		val = "";
		let current = image.data.string("x00181151"); // 曝光参数
		if (current) {
			if (current.indexOf(".") !== -1)
				current = current.substring(0, current.indexOf("."));
		}
		if (current && current.length > 0) {
			current += "mA";
			val += current;
		}
		let kvp = image.data.string("x00180060"); // 电压值
		if (kvp) {
			if (kvp.indexOf(".") !== -1) kvp = kvp.substring(0, kvp.indexOf("."));
		}
		if (kvp && kvp.length > 0) {
			kvp += "kV";
			val += " " + kvp;
		}
		let exposuretime = image.data.string("x00181150");
		if (exposuretime) {
			if (exposuretime.indexOf(".") !== -1)
				exposuretime = exposuretime.substring(0, exposuretime.indexOf("."));
		}
		if (exposuretime && exposuretime.length > 0) {
			exposuretime += "ms";
			val += " " + exposuretime;
		}
		let exposure = image.data.string("x00181152");
		if (exposure) {
			if (exposure.indexOf(".") !== -1)
				exposure = exposure.substring(0, exposure.indexOf("."));
		}
		if (exposure && exposure.length > 0) {
			exposure += "mAs";
			val += " " + exposure;
		}
		this.Exposure = val;

		let tr = image.data.string("x00180080"); // 重复时间
		let te = image.data.string("x00180081"); // 回响时间
		if (tr && te) {
			// 拍片参数
			this.TrTe = "TR:" + tr + " TE:" + te;
		}

		val = image.data.string("x00180082"); // 倒转时间TI
		if (val) this.InversionTime = "TI:" + val;
		val = image.data.string("x00181314"); // 翻转角度FA
		if (val) this.FlipAngle = "FA:" + val;
		val = image.data.string("x00189073"); // 采集时长AD
		if (val) this.AcquisitionDuration = "AD:" + val;
	}

	readOverlayData(image) {
		let val, tag;
		val = image.data.uint16("x60000010");
		if (val) {
			this.overlay.rows = val;
		}

		val = image.data.uint16("x60000011");
		if (val) {
			this.overlay.columns = val;
		}

		val = image.data.string("x60000040");
		if (val) {
			this.overlay.type = val;
		}

		this.overlay.origin[0] = image.data.int16("x60000050", 0) - 1;
		this.overlay.origin[1] = image.data.int16("x60000050", 1) - 1;

		// let tag = image.data.elements["x60000050"];
		// if (tag) {
		// 	val = readTagAsString(
		// 		image.data.byteArray,
		// 		tag.dataOffset,
		// 		tag.length,
		// 		tag.vr
		// 	);
		// 	this.overlay.origin[0] = parseInt(val.split("\\")[0]);
		// 	this.overlay.origin[1] = parseInt(val.split("\\")[1]);
		// }

		val = image.data.uint16("x60000100");
		if (val) {
			this.overlay.bitsAllocated = val;
		}

		tag = image.data.elements["x60003000"];
		// console.log("readOverlayData, tag:", tag, image);
		// const pixData = image.getPixelData();
		// console.log("pixData:", pixData);
		// console.log(`Array elements: ${array.join(', ')}`);

		if (tag) {
			// this.overlay.data = new Uint8Array(tag.length);
			// for (let i = 0; i < tag.length; i++) {
			// 	const lowByte = image.data.byteArray[tag.dataOffset + i];
			// 	this.overlay.data[i] = lowByte;
			// }

			// console.log(JSON.stringify(array, null, 2));
			const wordLen = Math.floor(tag.length / 2);
			this.overlay.data = new Uint16Array(wordLen);
			for (let i = 0; i < wordLen; i++) {
				const lowByte = image.data.byteArray[tag.dataOffset + i * 2];
				const highByte = image.data.byteArray[tag.dataOffset + i * 2 + 1];
				this.overlay.data[i] = (highByte << 8) + lowByte;
				// this.overlay.data[i] = (lowByte << 8) + highByte;
			}
		}
	}

	createThumb(type, size = 100) {
		// const image = await cornerstoneDICOMImageLoader.wadouri.loadImage(this.imageId).promise;
		return new Promise(async (res, rej) => {
			if (this.mime === "application/pdf") {
				const imgUri = new URL("@/assets/images/pdf.png", import.meta.url).href;
				res(imgUri);
				return;
			}
			const elDiv = document.createElement("div");
			let divW = this.width;
			let divH = this.height;
			let ratio = divW / divH;

			if (size != 0) {
				if (this.width > size) {
					divW = size;
					divH = divW / ratio;
				} else if (this.height > size) {
					divH = size;
					divW = divH * ratio;
				}
			}

			elDiv.style.width = divW + "px";
			elDiv.style.height = divH + "px";
			elDiv.style.backgroundColor = "black";
			// elDiv.style.id = "dispexpimg";
			document.body.appendChild(elDiv);

			// console.log("createJpg, elDiv:", cvs);
			// const renderingEngineId = "thumbRenderingEngine";
			let renderingEngine = getRenderingEngine(renderingEngineId2d);
			if (!renderingEngine) {
				renderingEngine = new RenderingEngine(renderingEngineId2d);
				console.log("createJpg create new renderingEngine:", renderingEngineId2d);
			}

			// Create a stack viewport
			const viewportId = "THUMBNAIL_STACK_" + this.sopInsUid;
			const viewportInput = {
				viewportId,
				type: ViewportType.STACK,
				element: elDiv,
				defaultOptions: {
					background: [0, 0, 0]
				}
			};

			renderingEngine.enableElement(viewportInput);

			// Get the stack viewport that was created
			let viewport = renderingEngine.getViewport(viewportId);
			const stack = [this.imageId];
			await viewport.setStack(stack);
			viewport.render();

			setTimeout(() => {
				const cvs = elDiv.querySelector("canvas");
				// console.log("createJpg, cvs:", cvs);
				if (type === "png") {
					const imgUri = cvs.toDataURL("image/png");
					renderingEngine.disableElement(viewportId);
					elDiv.remove();
					res(imgUri);
				} else if (type === "jpg") {
					const imgUri = cvs.toDataURL("image/jpeg");
					renderingEngine.disableElement(viewportId);
					elDiv.remove();
					res(imgUri);
				} else {
					cvs.toBlob(
						function (blob) {
							renderingEngine.disableElement(viewportId);
							elDiv.remove();
							res(blob);
						},
						"image/jpeg",
						1
					);
				}
			}, 100);
		});
	}

	async readTagList() {
		let tagdata = [];
		// const image = await cornerstoneDICOMImageLoader.wadouri.loadImage(
		// 	this.imageId
		// ).promise;

		const image = await imageLoader.loadAndCacheImage(this.imageId);

		// console.log("image:", image);
		// debugger;

		let charset = image.data.string("x00080005") || "ISO_IR 100";
		let isUtf8 = charset.indexOf("ISO_IR 192") != -1;
		const tags2 = [];
		const tags = [];
		for (let key in image.data.elements) {
			const atag = {};
			const elem = image.data.elements[key];
			atag.tagid = "(" + key.substring(1, 5) + "," + key.substring(5) + ")";
			atag.tagid = atag.tagid.toUpperCase();
			atag.vr = elem.vr;
			atag.len = elem.length;
			atag.vm = image.data.numStringValues(key) || 0;
			atag.desc = DcmTagsDesc[key] || "UnkownTag";

			const isMeta = key.substring(1, 5) == "0002";

			if (key === "x7fe00010") {
				const pixLen = elem.length > 32 ? 32 : elem.length;
				atag.value = this.readNPixelAsHexString(
					image.data.byteArray,
					elem,
					pixLen
				);
				// const byteArr = image.data.byteArray.slice(
				// 	elem.dataOffset,
				// 	elem.dataOffset + pixLen
				// );

				// console.log("byteArr:", byteArr);
			} else {
				if (atag.vr === "US" || atag.vr === "UL") {
					atag.value = image.data.uint16(key) + "";
				} else if (atag.vr === "FL") {
					atag.value = image.data.float(key) + "";
				} else if (atag.vr === "FD") {
					atag.value = image.data.double(key) + "";
				} else if (atag.vr === "SS") {
					atag.value = image.data.int16(key) + "";
				} else if (atag.vr === "SQ") {
					atag.value = "";
					if (isMeta) {
						tags2.push(atag);
					} else {
						tags.push(atag);
					}
					this.readTagSQ(isMeta ? tags2 : tags, elem.items, isUtf8, 1);

					const endsq = {};
					endsq.tagid = "(FFFE,E0DD)";
					endsq.vr = "";
					endsq.vm = 0;
					endsq.len = 0;
					endsq.desc = DcmTagsDesc["xfffee0dd"];
					endsq.value = "";
					if (isMeta) {
						tags2.push(endsq);
					} else {
						tags.push(endsq);
					}
				} else {
					atag.value = readTagAsString(
						image.data.byteArray,
						elem.dataOffset,
						elem.length
					);
					if (atag.value) {
						atag.value = decodeChinese(atag.value, isUtf8);
					}
				}

				//截取长度
				// atag.value = atag.value.toString().substring(0, 200);
				// atag.value = atag.value.toString();
			}

			//dicom tag第一个值不为02的放列表后面显示
			if (atag.vr !== "SQ") {
				if (isMeta) {
					tags2.push(atag);
				} else {
					tags.push(atag);
				}
			}
		}

		tagdata = [...tags2, ...tags];

		return tagdata;
	}

	readTagSQ(arr, items, isUtf8, level) {
		// console.log('items,',items);
		items.forEach(item => {
			const image = item.dataSet;
			const itemtag = {};
			itemtag.tagid =
				"(" + item.tag.substring(1, 5) + "," + item.tag.substring(5) + ")";
			itemtag.tagid = getNSpace(level) + itemtag.tagid;
			itemtag.tagid = itemtag.tagid.toUpperCase();
			itemtag.len = item.length;
			itemtag.vr = "";
			itemtag.value = "";
			itemtag.vm = 0;
			itemtag.desc = DcmTagsDesc[item.tag] || "";
			arr.push(itemtag);

			for (let key in image.elements) {
				const elem = image.elements[key];
				const atag = {};
				atag.tagid =
					"(" + elem.tag.substring(1, 5) + "," + elem.tag.substring(5) + ")";
				if (elem.tag === "xfffee00d") atag.tagid = getNSpace(level) + atag.tagid;
				else atag.tagid = getNSpace(level + 1) + atag.tagid;
				atag.tagid = atag.tagid.toUpperCase();
				atag.vr = elem.vr;
				atag.len = elem.length;
				atag.vm = image.numStringValues(elem.tag) | 0;
				atag.desc = DcmTagsDesc[elem.tag] || "UnkownTag";

				if (elem.tag === "x7fe00010") {
					const pixLen = elem.length > 32 ? 32 : elem.length;
					atag.value = this.readNPixelAsHexString(
						image.byteArray,
						elem,
						pixLen
					);
					// const byteArr = image.data.byteArray.slice(
					// 	elem.dataOffset,
					// 	elem.dataOffset + pixLen
					// );
					// console.log("byteArr:", byteArr);
				} else {
					if (atag.vr === "US" || atag.vr === "UL") {
						atag.value = image.uint16(elem.tag) + "";
					} else if (atag.vr === "FL") {
						atag.value = image.float(elem.tag) + "";
					} else if (atag.vr === "FD") {
						atag.value = image.double(elem.tag) + "";
					} else if (atag.vr === "SS") {
						atag.value = image.int16(elem.tag) + "";
					} else if (atag.vr === "SQ") {
						atag.value = "";
						arr.push(atag);
						this.readTagSQ(arr, elem.items, isUtf8, level + 2);
						const endsq = {};
						endsq.tagid = "(FFFE,E0DD)";
						endsq.vr = "";
						endsq.vm = 0;
						endsq.len = 0;
						endsq.desc = DcmTagsDesc["xfffee0dd"];
						endsq.value = "";
						arr.push(endsq);
					} else {
						atag.value = readTagAsString(
							image.byteArray,
							elem.dataOffset,
							elem.length
						);
						// if (atag.value === undefined) atag.value = "";
						if (atag.value) {
							atag.value = decodeChinese(atag.value, isUtf8);
						}
					}
				}
				if (atag.vr !== "SQ") arr.push(atag);
			}
		});
	}

	readNPixelAsHexString(byteArray, tag, n) {
		let str = "";
		const step = tag.vr === "OW" ? 2 : 1;
		for (let i = 0; i < n; i += step) {
			const lowByte = byteArray[tag.dataOffset + i].toString(16);
			if (step === 2) {
				const highByte = byteArray[tag.dataOffset + i + 1].toString(16);
				str += highByte + lowByte + " ";
			} else {
				str += lowByte + " ";
			}
		}
		return str.toUpperCase();
	}
}
